package com.dries.portal.module.convener.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dries.common.api.CommonResult;
import com.dries.common.api.ResultCode;
import com.dries.common.exception.ApiException;
import com.dries.portal.module.chat.constants.ChatConstant;
import com.dries.portal.module.chat.entity.GroupChat;
import com.dries.portal.module.chat.service.IGroupChatService;
import com.dries.portal.module.convener.dto.ConvenerCreateParams;
import com.dries.portal.module.convener.entity.Convener;
import com.dries.portal.module.convener.entity.ConvenerLikes;
import com.dries.portal.module.convener.entity.JoinConvener;
import com.dries.portal.module.convener.enums.ConvenerPaymentType;
import com.dries.portal.module.convener.enums.JoinConvenerType;
import com.dries.portal.module.convener.mapper.ConvenerMapper;
import com.dries.portal.module.convener.service.IConvenerLikesService;
import com.dries.portal.module.convener.service.IConvenerService;
import com.dries.portal.module.convener.service.IJoinConvenerService;
import com.dries.portal.module.convener.vo.ConvenerVo;
import com.dries.portal.module.convener.vo.ShopDetailVo;
import com.dries.portal.module.user.entity.UserEntity;
import com.dries.portal.module.user.service.UserService;
import com.dries.portal.module.xxshop.service.IGoodsService;
import com.dries.portal.module.xxshop.service.IUserorderService;
import com.dries.portal.module.xxshop.service.IUserordergoodsService;
import com.dries.portal.module.xxshop.service.IXXshopActivityService;
import com.dries.portal.module.xxshop.vo.UserOrderInfoVo;
import com.dries.security.service.RedisService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@DS("master")
@Slf4j
@Service
public class ConvenerServiceImpl extends ServiceImpl<ConvenerMapper, Convener> implements IConvenerService {

    @Resource
    private UserService userService;
    @Resource
    private IJoinConvenerService joinConvenerService;
    @Resource
    private IConvenerLikesService convenerLikesService;
    @Resource
    private IGroupChatService groupChatService;
    @Resource
    private RedisService redisService;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private IXXshopActivityService shopActivityService;
    @Resource
    private IGoodsService goodsService;
    @Resource
    private IUserorderService userorderService;
    @Resource
    private IUserordergoodsService userordergoodsService;


    /**
     *  发起召集
     */
    // @GlobalTransactional
    @Transactional
    @Override
    public Convener createConvener(String name, ConvenerCreateParams createParams) {

        Convener con = new Convener();
        // con.setOrderId(Long.parseLong(orderId));
        BeanUtils.copyProperties(createParams, con);
        save(con);

        Date showTime = con.getShowTime();
        long delayTime = (showTime.getTime() - con.getStartTime().getTime()) / 1000;
        // 定时任务
        rabbitTemplate.convertAndSend("convener_exchange", "convener", con,
                new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setHeader("x-delay", delayTime);
                        return message;
                    }
                }
        );
        // 创建聊天房间
        GroupChat chat = new GroupChat();
        chat.setId(con.getCid());
        chat.setGroupCode(IdUtil.simpleUUID());
        chat.setGroupUserId(con.getUserId());
        chat.setGroupType(con.getActivity());
        chat.setGroupName(con.getTitle());
        chat.setGroupUserName(name);
        chat.setGroupUserAvatar(con.getUserAvatar());
        groupChatService.save(chat);
        redisService.sAdd(ChatConstant.CHAT_GROUP_ONLINE_KEY + con.getCid(), name);

        JoinConvener joinConvener = new JoinConvener();
        joinConvener.setConvenerId(con.getCid());
        joinConvener.setMobile(con.getMobile());
        joinConvener.setStatus(JoinConvenerType.SIGNUP.getCode());
        joinConvener.setUserId(con.getUserId());
        joinConvener.setUserAvatar(con.getUserAvatar());
        joinConvener.setUserName(con.getUserName());
        joinConvenerService.save(joinConvener);

        return con;
    }

    /**
     * 开始召集 下订单
     * @param name
     * @param convenerId
     * @return
     */
    @GlobalTransactional
    @Override
    public UserOrderInfoVo startConvener(String name, Integer convenerId) {

        Convener convener = getById(convenerId);
        if (!convener.getUserName().equals(name)) {
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }

        return userorderService.createOrderByConvener(convener);
    }

    /**
     * 根据用户名展示到主页的召集信息
     * @param
     * @return
     */
    @Override
    public Convener queryConvener(Integer cid) {
        //把召集的信息显示到主页
        //根据召集列表的id查询出召集的信息
        Convener convener = getById(cid);
        if(convener == null){
            CommonResult.failed("该条数据不存在！！");
        }
        return convener;

    }

    @Override
    public void senDelay() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = formatter.format(LocalDateTime.now());
        System.out.println("消息发送时间:"+format);

        rabbitTemplate.convertAndSend("convener_exchange", "convener", "测试传输延迟消息",
                new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setHeader("x-delay",5000);
                        return message;
                    }
                }
        );
    }

    @Override
    public PageInfo<ConvenerVo> getJoinConvener(String userId, Integer pageNum, Integer pageSize) {

        Set<Object> roomIds = redisService.sMembers(ChatConstant.CONVENER_USER_KEY + userId);
        if (CollUtil.isEmpty(roomIds)) {
            return new PageInfo<>(new ArrayList<>());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Convener> list = list(new QueryWrapper<Convener>().lambda()
                .in(Convener::getCid, roomIds)
                .orderByDesc(Convener::getStartTime)
        );

        if (CollUtil.isNotEmpty(list)) {
            List<Integer> cIds = list.stream().map(Convener::getCid).collect(Collectors.toList());
            List<ConvenerLikes> likes = convenerLikesService.list(new QueryWrapper<ConvenerLikes>().lambda().in(ConvenerLikes::getConvenerId, cIds));
            List<ConvenerVo> convenerVos = list.stream().map(e -> {
                ConvenerVo convenerVo = new ConvenerVo();
                BeanUtils.copyProperties(e, convenerVo);
                List<ConvenerLikes> myLikes = likes.stream().filter(l -> Objects.equals(l.getConvenerId(), e.getCid()))
                        .peek(like -> {
                            if (String.valueOf(like.getUserId()).equals(userId)) {
                                convenerVo.setLikes(true);
                            }
                        })
                        .collect(Collectors.toList());
                convenerVo.setConvenerLikes(myLikes);
                Set<Object> users = redisService.sMembers(ChatConstant.CHAT_GROUP_ONLINE_KEY + convenerVo.getCid());
                if (CollUtil.isNotEmpty(users)) {
                    convenerVo.setOnlineUser(users.size());
                }
                convenerVo.setPaymentType(ConvenerPaymentType.of(e.getPaymentType()));
                convenerVo.setShopDetail(JSONUtil.toBean(e.getShopDetail(), ShopDetailVo.class));
                return convenerVo;
            }).collect(Collectors.toList());
            return new PageInfo<>(convenerVos);
        }
        return new PageInfo<>(new ArrayList<>());
    }

    @Override
    public ConvenerVo getConvenerInfoByOrderId(Long orderId) {

        UserEntity user = userService.getCurrentUser().getData();

        Convener convener = getOne(new QueryWrapper<Convener>().lambda().eq(Convener::getOrderId, orderId));
        if (convener != null) {
            List<ConvenerLikes> list = convenerLikesService.list(new QueryWrapper<ConvenerLikes>().lambda().eq(ConvenerLikes::getConvenerId, convener.getCid()));
            ConvenerVo convenerVo = new ConvenerVo();
            BeanUtils.copyProperties(convener, convenerVo);
            convenerVo.setShopDetail(JSONUtil.toBean(convener.getShopDetail(), ShopDetailVo.class));
            convenerVo.setConvenerLikes(list);

            convenerVo.setPaymentType(ConvenerPaymentType.of(convener.getPaymentType()));

            if (convenerVo.getUserName().equals(user.getUsername())) {
                convenerVo.setLikes(true);
            }
            Set<Object> users = redisService.sMembers(ChatConstant.CHAT_GROUP_ONLINE_KEY + convenerVo.getCid());
            if (CollUtil.isNotEmpty(users)) {
                convenerVo.setOnlineUser(users.size());
            }

            return convenerVo;
        }

        return null;
    }
}